using System;
using System.Collections.Generic;
using System.Text;

namespace Adoor.Collections.Generic
{
    public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>
    {
        private System.Collections.Generic.Dictionary<TKey, TValue> innerDic;

        public event DictionaryChangeEventHandler<TKey, TValue> DictionaryChanged;

        protected virtual void OnDictionaryChanged(DictionaryChangeAction action,
            TKey key, TValue value)
        {
            if (DictionaryChanged != null)
            {
                DictionaryChangeEventArgs<TKey, TValue> e = new DictionaryChangeEventArgs<TKey, TValue>(action, key, value);
                DictionaryChanged(this, e);
            }
        }

        public Dictionary()
        {
            this.innerDic = new System.Collections.Generic.Dictionary<TKey, TValue>();
        }

        #region IDictionary<TKey,TValue> Members

        public virtual void Add(TKey key, TValue value)
        {
            this.innerDic.Add(key, value);
            OnDictionaryChanged(DictionaryChangeAction.Add, key, value);
        }

        public virtual bool ContainsKey(TKey key)
        {
            return this.innerDic.ContainsKey(key);
        }

        public virtual ICollection<TKey> Keys
        {
            get { return innerDic.Keys; }
        }

        public virtual bool Remove(TKey key)
        {
            TValue value;
            if (!this.TryGetValue(key, out value))
                return false;

            innerDic.Remove(key);
            OnDictionaryChanged(DictionaryChangeAction.Remove, key, value);
            return true;
        }

        public virtual bool TryGetValue(TKey key, out TValue value)
        {
            return innerDic.TryGetValue(key, out value);
        }

        public virtual ICollection<TValue> Values
        {
            get { return innerDic.Values; }
        }

        public virtual TValue this[TKey key]
        {
            get
            {
                return innerDic[key];
            }
            set
            {
                this.innerDic[key] = value;
                OnDictionaryChanged(DictionaryChangeAction.Add, key, value);
            }
        }

        #endregion

        #region ICollection<KeyValuePair<TKey,TValue>> Members

        public virtual void Add(KeyValuePair<TKey, TValue> item)
        {
            this.innerDic.Add(item.Key, item.Value);
            OnDictionaryChanged(DictionaryChangeAction.Add, item.Key, item.Value);
        }

        public virtual void Clear()
        {
            OnDictionaryChanged(DictionaryChangeAction.Refresh, 
                default(TKey), default(TValue));
        }

        public virtual bool Contains(KeyValuePair<TKey, TValue> item)
        {
            return innerDic.ContainsKey(item.Key);
        }

        public virtual void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
        {
            ((ICollection<KeyValuePair<TKey,TValue>>)  innerDic).CopyTo(array, arrayIndex);
        }

        public virtual int Count
        {
            get { return innerDic.Count; }
        }

        public virtual bool IsReadOnly
        {
            get { return false; }
        }

        public virtual bool Remove(KeyValuePair<TKey, TValue> item)
        {
            bool result = innerDic.Remove(item.Key);
            if (result)
                OnDictionaryChanged(DictionaryChangeAction.Remove, item.Key, item.Value);

            return result;
        }

        #endregion

        #region IEnumerable<KeyValuePair<TKey,TValue>> Members

        public virtual IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            return innerDic.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return ((System.Collections.IEnumerable)innerDic).GetEnumerator();
        }

        #endregion
    }
}
